package random;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Random;

import core.SimpleGraph;
import core.Vertex;

public class BuildGraph {
	
	public void BuildRandomGraph(String fileName, String directory, int vertices, int dense, int maxCapacity, int minCapacity)
	    {
	     Random random = new Random();
	     try{
	         String dirName = directory;//           
	           if (dirName.equals ("")) {dirName = ".";}
	
		       File outputfile = new File(dirName, fileName);
	                  int[][] Graph = new int[vertices][vertices];
		              int n, m;
		              
	                         for ( n = 0; n < vertices; n++)
	                          for ( m = n+1; m < vertices; m++)
	                          {
	                              int randomInt = (random.nextInt((maxCapacity-minCapacity+1))+minCapacity) ;
	
	                              int k =(int) (1000.0*Math.random()/10.0);
	                              int b = (k < dense) ? 1 : 0;
	                              if(b == 0)
	                              {
	                                  Graph[n][m] = Graph[m][n] = b;
	                              }
	                              else
	                              {
	                                Graph[n][m] = Graph[m][n] = randomInt;
	                              }
	                            }
	               			  
	                      
	            PrintWriter output = new  PrintWriter(new FileWriter(outputfile));
	
	            for(int x = 0; x < Graph.length; x++)
	            {
	                if(x == 0)
	                {
	                    for(int y = 0; y < Graph[x].length; y++)
	                    {
	                        String value = String.valueOf(Graph[x][y]);
	                        if(y != 0)
	                        {
	                            if(value.equals("0") == false)
	                            {
	                                output.print("s " + String.valueOf(y) + " " +  value +"\n");
	                            }
	                        }
	                    }
	                }
	                else
	                {
	                    if(x == Graph.length-1)
	                    {
	                        for(int y = 0; y < Graph[x].length; y++)
	                        {
	                            String value = String.valueOf(Graph[x][y]);
	                            if(y != 0)
	                            {
	                                if(value.equals("0") == false)
	                                {
	                                    output.print(String.valueOf(y) + " t " +  value +"\n");
	                                }
	                            }
	                        }
	                    }
	                    else
	                    {
	                        for(int y = 0; y < Graph[x].length; y++)
	                        {
	                            String value = String.valueOf(Graph[x][y]);
	                            if(y != 0)
	                            {
	                                if(value.equals("0") == false)
	                                {
	                                    output.print(x + " " + String.valueOf(y) + " " +  value +"\n");
	                                }
	                            }
	                        }
	                    }
	                }
	                
	            }
	
	         output.close();
	       } 
	        catch (IOException e)
	          {
	            System.err.println("Error opening file" +e);
	            return;
	          }
	     //System.out.print("\nDone");
	 }
	
	/**
	 * Generates a new random graph, where each edge has a capacity evenly 
	 * distributed between the min and max.  Nodes s and t may randomly have edges 
	 * to any node.  The graph may either be uni-directional in which case each 
	 * internal node is numbered and an edge will only go from the lower to the 
	 * higher node.  In a bi-directional graph internal nodes may have edges going 
	 * any which way.
	 * @author Michael Pitts not really based on above code
	 * @param vertices is the number of vertices to be in the graph, not counting
	 * the source and sink.
	 * @param dense is the probability, between 0.0 and 1.0, of any two vertices 
	 * v and w, having a connection v -> w.
	 * @param max is the maximum capacity of any given edge.
	 * @param min is the minimum capacity of any given edge.
	 * @param bi_directional if false nodes will only form edges to nodes with higher 
	 * numbers, or names.  If true, an edge can go in either direction and two nodes 
	 * may thus have two edges between them, v -> w and w -> v, with different 
	 * capacities.
	 * @return a new SimpleGraph where each pair of vertices have a random chance 
	 * of being connected by an edge.
	 */
	public static SimpleGraph generate(final int vertices, final double dense, 
			final int max, final int min, final boolean bi_directional) {
		final SimpleGraph graph = new SimpleGraph();
		final Vertex[] nodes = new Vertex[vertices];
		final Vertex source = graph.insertVertex(null, "s");
		final Vertex sink = graph.insertVertex(null, "t");
		final Random ran = new Random();
		for (int i = 0; i < nodes.length; i++) { // initialize nodes and s/t edges
			nodes[i] = graph.insertVertex(null, "" + i);
			if (ran.nextDouble() < dense) // edge from source
				graph.insertEdge(source, nodes[i], (ran.nextInt((max-min+1))+min), null);
			if (ran.nextDouble() < dense) // edge to sink
				graph.insertEdge(nodes[i], sink, (ran.nextInt((max-min+1))+min), null);
		}
		if (bi_directional) { // edges can go either, or both, directions
			for (int i = 0; i < nodes.length; i++) {
				for (int j = 0; j < nodes.length; j++) {
					if (ran.nextDouble() < dense && i != j)
						graph.insertEdge(nodes[i], nodes[j], 
								(ran.nextInt((max-min+1))+min), null);
				}
			}
		} else { // edges only go from lower nodes to higher numbered nodes
			for (int i = 0; i < nodes.length - 1; i++) {
				for (int j = i+1; j < nodes.length; j++) {
					if (ran.nextDouble() < dense)
						graph.insertEdge(nodes[i], nodes[j], 
								(ran.nextInt((max-min+1))+min), null);
				}
			}
		}
		return graph;
	}
}